﻿using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Chloe.Ext.Attribute;
using Newtonsoft.Json.Linq;
using System.IO;
using FrmLib.Orm;

namespace Ace.Web.ViewTag
{
    public class VueTagHelperComm
    {

        public static JArray combineJarr(JArray oldjar, JArray newjar)
        {
            foreach (var one in newjar)
            {
                var newone = one;
                var oldOne = (from x in oldjar where x["Name"].ToString().ToLower() == one["Name"].ToString().ToLower() select x).FirstOrDefault();
                if (oldOne != null)
                {
                    oldjar.Remove(oldOne);
                    newone = combineVmJobj(oldOne as JObject, one as JObject);
                }


                oldjar.Add(newone);

            }
            return oldjar;
        }
        public static JObject combineVmJobj(JObject oldjobj, JObject newjobj)
        {
            foreach (var key in newjobj.Properties())
            {

                if (key.Name == "Struct")
                {
                    oldjobj["Struct"] = combineJarr(oldjobj["Struct"] as JArray, newjobj["Struct"] as JArray);
                    continue;
                }
                if (FrmLib.Extend.tools_static.jobjectHaveKey(oldjobj, key.Name))
                {
                    oldjobj[key.Name] = newjobj[key.Name];

                }
                else
                    oldjobj.Add(key.Name, newjobj[key.Name]);
            }
            return oldjobj;
        }
        public static JObject getModelConfJobj(string className)
        {
            var allasm = (from x in AppDomain.CurrentDomain.GetAssemblies() where x.FullName.Contains("Model") select x);
            Type modeltype = null;
            foreach (var one in allasm)
            {
                modeltype = (from x in one.GetTypes() where x.Name == className select x).FirstOrDefault();
            }
            JObject jobj = null;
            if (modeltype != null)
            {
                var confattr = (from x in modeltype.GetCustomAttributes(true) where x.GetType() == typeof(ClassViewConfAttribute) select x).FirstOrDefault() as ClassViewConfAttribute;
                if (confattr != null)
                    jobj = JObject.Parse(confattr.jsonConf);
            }
            var fbasepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "configs", "ViewModelConf");
            var fn1 = Path.Combine(fbasepath, className + ".json");
            if (File.Exists(fn1))
            {
                var fcontent = File.ReadAllText(fn1);
                JObject tmpobj = JObject.Parse(fcontent);
                jobj = combineVmJobj(jobj, tmpobj);
            }
            fn1 = Path.Combine(fbasepath, className + ".extend.json");
            if (File.Exists(fn1))
            {
                var fcontent = File.ReadAllText(fn1);
                JObject tmpobj = JObject.Parse(fcontent);
                jobj = combineVmJobj(jobj, tmpobj);
            }
            return jobj;
        }
        /// <summary>
        /// 模型类型的 viewform表单，视图模型名称为主键，表单内容为值
        /// </summary>
        public static Dictionary<string, string> tagViewFormDic = new Dictionary<string, string>();
        public static Dictionary<string, string> tagViewJsDic = new Dictionary<string, string>();
    }
    [HtmlTargetElement("VueMvcTable")]
   public class VueMvcTableTagHelper : TagHelper
    {
       
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            string style = output.Attributes.Where(a => a.Name == "style").FirstOrDefault()?.Value.ToString() ?? null;
           string tmpMainStr = output.Attributes.Where(a => a.Name == "isMain").FirstOrDefault()?.Value.ToString() ?? null;
            string tmpSlaveStr = output.Attributes.Where(a => a.Name == "isSlave").FirstOrDefault()?.Value.ToString() ?? "false";
            bool isSlave = bool.Parse(tmpSlaveStr);
            string columns = "mainTableConfig.columns";
            string tableData = "mainTableConfig.tableData";
            string RowClick = "mainRowClick";
            string PageChange = "mainPageChange";
            string PageSizeChange = "mainPageSizeChange";
            string TotalCount = "mainTotalCount";
            string pageSize = "pageSize";
            string PageIndex = "mainPageIndex";
          string  sortChange = output.Attributes.Where(a => a.Name == "sortChange").FirstOrDefault()?.Value.ToString() ?? null;
            if (isSlave)
            {
                columns = "slaveTableConfig.columns";
                tableData = "slaveTableConfig.tableData";
                RowClick = "slaveRowClick";
                PageChange = "slavePageChange";
                PageSizeChange = "slavePageSizeChange";
                TotalCount = "slaveTotalCount";
                PageIndex = "slavePageIndex";
            }
            
           
            //output.Attributes.RemoveAll("style");
            output.TagName = "Div";
            output.Content.AppendLine();
            var tablecontent = string.Format(VueComponentTmplate.masterVueTable, columns, tableData, RowClick, sortChange, PageChange, PageSizeChange, TotalCount, pageSize, PageIndex);
            output.Content.AppendText(tablecontent);
            output.Content.AppendLine();


        }
    }
    [HtmlTargetElement("VueElMvcDialog")]
    public class VueElMvcDialogTagHelper : TagHelper
    {

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            
            string style = output.Attributes.Where(a => a.Name == "style").FirstOrDefault()?.Value.ToString() ?? null;
            string className = output.Attributes.Where(a => a.Name == "modelname").FirstOrDefault()?.Value.ToString() ?? null;
            if (string.IsNullOrEmpty(className))
            {
                return;

            }
            if (VueTagHelperComm.tagViewFormDic.ContainsKey(className))
            {
                output.Content.AppendText(VueTagHelperComm.tagViewFormDic[className]);
                return;
            }
            var jobj = VueTagHelperComm.getModelConfJobj(className);
           
            if (jobj == null)
                return;
              var cvm= Newtonsoft.Json.JsonConvert.DeserializeObject<FrmLib.Orm.ClassViewStructDefine>(jobj.ToString());
            StringBuilder sb = new StringBuilder();
            StringBuilder rowsb = new StringBuilder();
            var orderPorertysInForm = (from x in cvm.Struct where x.Visible orderby x.posRow*10+x.posCol select x).ToList();
           
            var colspan = 24 / cvm.colCountPerRow;
            int i = 0,coli=1;

            foreach (var obj in orderPorertysInForm)
            {
                if (coli >= cvm.colCountPerRow)
                {
                    sb.AppendLine(string.Format(VueComponentTmplate.vueFormRow, 8, rowsb.ToString()));
                    rowsb.Clear();
                }
                var editorstr = getFormEditorContent(obj);
                var colstring = string.Format(VueComponentTmplate.vueFormCol, obj.DisplayTag, obj.Name, colspan, editorstr);
                rowsb.AppendLine(colstring);
                coli++;              

            }

            lock (VueTagHelperComm.tagViewFormDic)
            {
                if(!VueTagHelperComm.tagViewFormDic.ContainsKey(className))
                    VueTagHelperComm.tagViewFormDic.Add(className, sb.ToString());
            }
            output.Content.AppendText(sb.ToString());
        }
        private string getFormEditorContent(VmPropertyDefine attr)
        {
            string result = null;
            enumVmEditorType petype = (enumVmEditorType)Enum.Parse(typeof(enumVmEditorType), attr.editorType);
            switch (petype)
            {
                case (enumVmEditorType.input):
                    result = string.Format(VueComponentTmplate.vueFormInputEditor, attr.Name, attr.Disable, attr.DisplayTag);
                    break;

            }
            return result;
        }

        }

    /// <summary>
    /// vue script columns
    /// </summary>
    [HtmlTargetElement("VueElTableColumn")]
    public class VueBaseScriptTagHelper : TagHelper
    {

    }

    public static class TagHelperContentExtension
    {
        public static TagHelperContent AppendText(this TagHelperContent content, string text)
        {
            content.AppendHtml(text);
            return content;
        }
        public static TagHelperContent AppendText(this TagHelperContent content, string format, params object[] args)
        {
            content.AppendFormat(format, args);
            return content;
        }
        public static TagHelperContent AppendLine(this TagHelperContent content)
        {
            content.AppendHtml(Environment.NewLine);
            return content;
        }
    }
}
